package edu.utexas.esel.jgraphpad.archpadplugin.graph;

import org.jgraph.graph.AttributeMap;
import org.jgraph.graph.DefaultGraphCell;

import edu.utexas.esel.jgraphpad.archpadplugin.ArchPadPlugin;
import edu.utexas.esel.jgraphpad.archpadplugin.model.Element;
import edu.utexas.esel.jgraphpad.archpadplugin.model.ElementTreeNode;
import edu.utexas.esel.jgraphpad.archpadplugin.model.IdManager;

/**
 * Custom cell that contains an {@link ContainerCellReference} as its user
 * object.
 *
 * @author svetoslavganov@mail.utexas.edu
 *
 */
public class ElementGraphCell extends DefaultGraphCell {

	/**
	 * The unique id of an element.
	 */
	public static final String ATTRIBUTE_ID = "id";

	/**
	 * The element type represented by an {@link ElementGraphCell}.
	 */
	public static final String ATTRIBUTE_ELEMENT_TYPE = "elementType";

	/**
	 * Component element type.
	 */
	public static final String TYPE_COMPONENT =
		ArchPadPlugin.TYPE_DECLARATION_COMPONENT.getName();

	/**
	 * Connector element type.
	 */
	public static final String TYPE_CONNECTOR =
		ArchPadPlugin.TYPE_DECLARATION_CONNECTOR.getName();

	/**
	 * Region element type.
	 */
	public static final String TYPE_REGION =
		ArchPadPlugin.TYPE_DECLARATION_REGION.getName();

	/**
	 * The color for a region.
	 */
	public static final String ATTRIBUTE_REGION_COLOR = "regionColor";

	/**
	 * The color for a region.
	 */
	public static final String ATTRIBUTE_REGION_ENABELD = "regionEnabled";

	private static final long serialVersionUID = 1L;

	/**
	 * Creates a new instance.
	 */
	public ElementGraphCell() {
        this(null, new AttributeMap());	
	}

	public ElementGraphCell(Element element, AttributeMap attributes) {
		super(element, attributes);
		setUserObject(element);
	}

	/**
	 * Gets the unique id of the element.
	 *
	 * @return The id.
	 */
	public Integer getId() {
	    return (Integer) attributes.get(ElementTreeNode.ATTRIBUTE_ID);	
	}

	@Override
	@SuppressWarnings("unchecked")
	// KGraph uses raw types
	public void setUserObject(Object userObject) {
		if (userObject instanceof Element) {
			Element element = (Element) userObject;
			element.setContainerCell(this);

			// if the element has ID this is as the ID of the cell as well
		    ElementTreeNode root = (ElementTreeNode) element.getRoot();
		    String id = root.getAttribute(ElementTreeNode.ATTRIBUTE_ID);
		    IdManager idManager = IdManager.getInstance();

		    if (id != null) {
			    idManager.reserveId(Integer.parseInt(id));
		    } else {
			    id = String.valueOf(idManager.generateId());
			    root.setAttribute(ElementTreeNode.ATTRIBUTE_ID, id);
		    }

    		attributes.put(ElementTreeNode.ATTRIBUTE_ID, id);
		}

		super.setUserObject(userObject);
	}

	@Override
	public Object clone() {
		ElementGraphCell clone = (ElementGraphCell) super.clone();
		clone.setUserObject(((Element) userObject).clone());
		return super.clone();
	}
	
	/**
	 * Gets the value of an attribute.
	 *
	 * @param <T> The type of the return value.
	 * @param attrribute The attribute name.
	 * @return The value of the attribute if such, null otherwise.
	 */
	@SuppressWarnings("unchecked")
	// For convenience to avoid casting every time a property is fetched
    public <T> T getAttribute(String attrribute) {
		return (T) attributes.get(attrribute);
	}
	
	/**
	 * Sets the value of an attribute.
	 *
	 * @param <T> The type of the return value.
	 * @param attrribute The attribute name.
	 * @return The old value of the attribute if such, null otherwise.
	 */
	@SuppressWarnings("unchecked")
	// For convenience to avoid casting every time the return result
    public <T> T setAttribute(String attribute, T value) {
		return (T) attributes.put(attribute, value);
	}
}
